package com.dongdong.bookstore.module.cms.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dongdong.bookstore.common.exception.Asserts;
import com.dongdong.bookstore.module.ams.model.Article;
import com.dongdong.bookstore.module.cms.model.User;
import com.dongdong.bookstore.module.cms.mapper.UserMapper;
import com.dongdong.bookstore.module.cms.service.CmsCacheService;
import com.dongdong.bookstore.module.cms.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dongdong.bookstore.module.cms.viewmodel.UpdateUserParam;
import com.dongdong.bookstore.module.cms.viewmodel.UpdateUserPasswordParam;
import com.dongdong.bookstore.module.cms.viewmodel.UserLoginParam;
import com.dongdong.bookstore.module.cms.viewmodel.UserRegistParam;
import com.dongdong.bookstore.module.ums.model.Resource;
import com.dongdong.bookstore.security.model.CustomUserDetails;
import com.dongdong.bookstore.security.model.UserCategory;
import com.dongdong.bookstore.security.utils.JwtTokenUtil;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * <p>
 * 会员表 服务实现类
 * </p>
 *
 * @author chiangkai
 * @since 2021-10-27
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private CmsCacheService cmsCacheService;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;


    @Override
    public UserDetails loadUserByName(String username) {
        UserDetails userDetails = null;
        User user = cmsCacheService.getUser(username);
        if (user == null) {
            QueryWrapper<User> wrapper = new QueryWrapper<>();
            wrapper.lambda().eq(User::getUsername, username);
            user = getOne(wrapper);
            if (user != null) {
                cmsCacheService.setUser(user);
            }
        }
        if (user != null) {
            user.setUserCategory(UserCategory.VIP);
            //防止用户和管理员同名
            user.setUsername("user:" + user.getUsername());
            userDetails = new CustomUserDetails(user, new ArrayList<Resource>());
        }
        return userDetails;
    }

    @Override
    public User userRegister(UserRegistParam param) {
        User user = new User();
        BeanUtils.copyProperties(param, user);
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(User::getUsername, param.getUsername());
        //判断用户名是否存在
        Integer judgeUsernameExist = userMapper.selectCount(wrapper);
        Asserts.gt0(judgeUsernameExist, "用户名已被注册");

        //判断手机号是否存在
        wrapper.clear();
        wrapper.lambda().eq(User::getTel, param.getTel());
        Integer judgeTelExist = userMapper.selectCount(wrapper);
        Asserts.gt0(judgeTelExist, "手机号已被注册");

        //判断邮箱是否存在
        wrapper.clear();
        wrapper.lambda().eq(User::getEmail, param.getEmail());
        Integer judgeEmailExist = userMapper.selectCount(wrapper);
        Asserts.gt0(judgeEmailExist, "邮箱已被注册");

        user.setPassword(passwordEncoder.encode(param.getPassword()));
        int insert = baseMapper.insert(user);
        if (insert > 0) {
            return baseMapper.selectOne(wrapper);
        }
        Asserts.fail("添加用户失败");
        return null;
    }


    @Override
    public UserDetails loadUserByName(String username, String email, String tel) {
        User user = null;
        if (username != null) {
            user = getUserByUsername(username);
        } else if (email != null) {
            user = getUserByEmail(email);
        } else {
            user = getUserByTel(tel);
        }
        if (user == null) {
            throw new UsernameNotFoundException("用户不存在");
        }
        // TODO ServiceImpl加载用户
        /**
         * ***********************未完成*****************************
         * */

        return null;
    }

    @Override
    public void judgeAdminExistByUsername(String username) {
        Asserts.notNull(getUserByUsername(username), "用户名已被注册");
    }

    @Override
    public void judgeAdminExistByTel(String tel) {
        Asserts.notNull(getUserByTel(tel), "手机号已被注册");
    }

    @Override
    public void judgeAdminExistByEmail(String email) {
        Asserts.notNull(getUserByEmail(email), "邮箱已被注册");
    }

    @Override
    public User getUserByUsername(String username) {
        User user = cmsCacheService.getUser(username);
        if (user == null) {
            QueryWrapper<User> wrapper = new QueryWrapper<>();
            wrapper.lambda().eq(User::getUsername, username);
            user = userMapper.selectOne(wrapper);
            if (user != null) {
                cmsCacheService.setUser(user);
            }
        }
        return user;
    }

    @Override
    public User getUserByTel(String tel) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(User::getTel, tel);
        return userMapper.selectOne(wrapper);
    }

    @Override
    public User getUserByEmail(String email) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(User::getEmail, email);
        return userMapper.selectOne(wrapper);

    }

    @Override
    public String refreshUserToken(String token) {

        return jwtTokenUtil.refreshHeadToken(token);
    }

    @Override
    public Page<User> userList(String keyword, Integer pageSize, Integer pageNum) {
        Page<User> page = new Page<>(pageNum, pageSize);
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        if (StrUtil.isNotEmpty(keyword)) {
            wrapper.lambda().like(User::getUsername, keyword);
            wrapper.lambda().or().like(User::getNickName, keyword);
            wrapper.lambda().or().like(User::getEmail, keyword);
            wrapper.lambda().or().like(User::getTel, keyword);
        }
        return page(page, wrapper);
    }

    @Override
    public boolean userUpdateBaseInfo(Long id, UpdateUserParam updateUserParam) {

        User user = new User();
        user = userMapper.selectById(id);
        BeanUtils.copyProperties(updateUserParam,user);
        boolean success = updateById(user);
        if(success){
            cmsCacheService.delUser(id);
            cmsCacheService.setUser(user);
        }

        return success;
    }

    @Override
    public void updatePassword(UpdateUserPasswordParam updateUserPasswordParam) {
        User user = getUserByUsername(updateUserPasswordParam.getUsername());
        Asserts.isNull(user, "用户不存在");
        Asserts.isFalse(passwordEncoder.matches(updateUserPasswordParam.getOldPassword(), user.getPassword()), "旧密码错误");
        user.setPassword(passwordEncoder.encode(updateUserPasswordParam.getNewPassword()));
        cmsCacheService.delUser(user.getId());
        cmsCacheService.setUser(user);
        Asserts.isFalse(updateById(user), "密码更新失败");


    }

    @Override
    public boolean userDel(Long id) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(User::getId, id);
        Asserts.isFalse(remove(wrapper), "删除用户失败");
        return true;
    }

    @Override
    public String login(UserLoginParam userLoginParam) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(User::getUsername, userLoginParam.getAccount()).or().eq(User::getTel, userLoginParam.getAccount());
        List<User> list = list(wrapper);
        Iterator<User> iterator = list.iterator();
        User target = null;
        while (iterator.hasNext()) {
            User user = iterator.next();
            if (passwordEncoder.matches(userLoginParam.getPassword(), user.getPassword())) {
                target = user;
                break;
            }
        }
        Asserts.isNull(target, "账号或密码错误");
        target.setUserCategory(UserCategory.VIP);
        UserDetails userDetail = loadUserByName(target.getUsername());
        //new CustomUserDetails(target, new ArrayList<Resource>());
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(userDetail, null, userDetail.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
        return jwtTokenUtil.generateToken(userDetail);
    }


    @Override
    public boolean userRenew(Long id) {

        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(User::getId, id);
        User user = userMapper.selectOne(wrapper);
        user.setDeleted(0);
        int update = userMapper.update(user, wrapper);
        if (update > 0) {
            return true;
        }
        Asserts.fail("恢复用户失败");
        return false;
    }


}
